/**
 * Project: core.common
 * 
 * File Created at 2016年4月4日
 * 
 * Copyright 2015-2015 dx.com Croporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * DongXue software Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with dx.com.
 */
package com.dx.pf.commons.balance;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/** 
* @ClassName: Context 
* @Description: 用于配置，该类是单例的并保证线程安全
* @author wuzhenfang(wzfbj2008@163.com)
* @date 2016年4月4日 下午11:46:29 
* @version V1.0 
*/
public class Context {
	private static volatile Context instance = null;
    private Map<Long, Integer> uriHashMap = new HashMap<Long, Integer>();//uri 维护列表，动态变化
    private HashAlgorithm hashAlgorithm = HashAlgorithm.MurMurHash;//默认使用MurMurHash，非安全HASH，但高效
    private List<ServerNode> atsServers = new ArrayList<ServerNode>();//服务器列表

    private Context() {
        System.out.println("Context初始化成功>>>");
    }

    /**
     * 获取BalanceContext对象
     * @return Context
     */
    public static Context getInstance() {
        if (instance == null) { // double check (jdk1.5+)
            synchronized (Context.class) {
                if (instance == null)
                    instance = new Context();
            }
        }
        return instance;
    }

    public boolean containsUri(String uri) {
        return !(uri == null || "".equals(uri.trim())) &&
                this.uriHashMap.containsKey(this.hashAlgorithm.hash(uri.trim()));
    }

    public HashAlgorithm getHashAlgorithm() {
        return hashAlgorithm;
    }

    /**
     * 设置hash算法
     * @param hashAlgorithm
     */
    public void setHashAlgorithm(HashAlgorithm hashAlgorithm) {
        this.hashAlgorithm = hashAlgorithm;
    }

    /**
     * 获取uri和服务器数量上次取模的值对应关系
     * @return
     */
    public Map<Long, Integer> getUriHashMap() {
        return uriHashMap;
    }

    /**
     * 增加新的URI
     *
     * @param uriHashCode URI的HASHCODE
     * @param mark
     */
    public void putUriHash(long uriHashCode, int mark) {
        uriHashMap.put(uriHashCode, mark);
    }

    public int getUriHash(long uriHashCode) {
        if (!uriHashMap.containsKey(uriHashCode)) return 0;
        return uriHashMap.get(uriHashCode);
    }

    public void removeUriHash(Long uriHashCode) {
        uriHashMap.remove(uriHashCode);
    }

    /**
     * 判断是否是热门uri
     * @param uriStr uri字符串
     * @return 是ture 否则false
     */
    public boolean isPopularUri(String uriStr) {
        return Context.getInstance().containsUri(uriStr);
    }

    /**
     * 获取服务器列表
     * @return
     */
    public List<ServerNode> getAtsServers() {
        return atsServers;
    }

    /**
     * 设置服务器列表
     * @param atsServers
     */
    public void setAtsServers(List<ServerNode> atsServers) {
        this.atsServers = atsServers;
    }

    /**
     * 支持动态的增加服务器节点
     * @param node
     */
    public void addAtsServer(ServerNode node) {
        this.atsServers.add(node);
    }

    /**
     * 支持动态的减少服务器节点,服务器减少后，轮询范围在下次访问时自动刷新
     * @param node
     */
    public void removeAtsServer(ServerNode node) {
        this.atsServers.remove(node);
    }

    /**
     * 获取随机一台服务器编号
     * @return
     */
    public int getRandServer() {
        return new Random().nextInt(atsServers.size()); //防止启动时都打到第一台server
    }

    /**
     * 便捷的Hash值计算
     * @param uri
     * @return
     */
    public long hash(String uri) {
        if (uri == null) return 0L;
        return this.hashAlgorithm.hash(uri.trim());
    }
}
